package org.example.paymentservice.service.impl;

import lombok.RequiredArgsConstructor;
import org.example.paymentservice.dto.PaymentRequest;
import org.example.paymentservice.entity.Order;
import org.example.paymentservice.entity.PaymentTransaction;
import org.example.paymentservice.repository.PaymentTransactionRepository;
import org.example.paymentservice.service.OrderProcessor;
import org.example.paymentservice.service.PaymentGateway;
import org.example.paymentservice.service.provider.PaymentProviderFactory;
import org.example.paymentservice.service.provider.PaymentProvider;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class PaymentGatewayImpl implements PaymentGateway {
    private final OrderProcessor orderProcessor;
    private final PaymentTransactionRepository transactionRepository;
    private final PaymentProviderFactory paymentProviderFactory;

    @Override
    @Transactional
    public PaymentTransaction processPayment(PaymentRequest paymentRequest) {
        Order order = orderProcessor.validateOrder(paymentRequest.getOrderId());
        PaymentProvider provider = paymentProviderFactory.getProvider(paymentRequest.getPaymentMethod());

        PaymentTransaction transaction = new PaymentTransaction();
        transaction.setOrder(order);
        transaction.setAmount(order.getAmount());
        transaction.setType(PaymentTransaction.TransactionType.PAYMENT);
        transaction.setPaymentProvider(paymentRequest.getPaymentMethod().toString());

        try {
            String transactionId = provider.processPayment(
                    order.getAmount(),
                    paymentRequest.getPaymentDetails()
            );

            transaction.setProviderTransactionId(transactionId);
            transaction.setStatus(PaymentTransaction.TransactionStatus.SUCCESS);
            orderProcessor.updateOrderStatus(order.getId(), Order.PaymentStatus.PAID);
        } catch (Exception e) {
            transaction.setStatus(PaymentTransaction.TransactionStatus.FAILED);
            transaction.setErrorMessage(e.getMessage());
            orderProcessor.updateOrderStatus(order.getId(), Order.PaymentStatus.FAILED);
        }

        return transactionRepository.save(transaction);
    }

    @Override
    public boolean validatePayment(String transactionId) {
        PaymentTransaction transaction = getTransactionDetails(transactionId);
        PaymentProvider provider = paymentProviderFactory.getProvider(
                Order.PaymentMethod.valueOf(transaction.getPaymentProvider())
        );
        return provider.validatePayment(transactionId);
    }

    @Override
    public PaymentTransaction getTransactionDetails(String transactionId) {
        return transactionRepository.findByProviderTransactionId(transactionId)
                .orElseThrow(() -> new EntityNotFoundException("Transaction not found"));
    }
}